package fiuba.algo3.mapa;

import java.util.ArrayList;
import java.util.Random;

import org.jdom2.Element;

import fiuba.algo3.obstaculo.*;
import fiuba.algo3.sorpresas.*;
import fiuba.algo3.vehiculo.Conductor;


public class Mapa {

	private Esquina[][] plano;
	private ArrayList<Calle> callesDelMapa = new ArrayList<Calle>();
	private Esquina largada;
	private Esquina llegada;
	private int tam;

	public Mapa(int tamanio) {
		
		this.tam = tamanio;
		this.crearMapa(tamanio);
		
		// seteo los puntos de partida (en cualquier esquina del costado
		// izquierdo) y de llegada (costado derecho)
		int aleatorio = new Random().nextInt(tamanio);
		this.setLargada(plano[aleatorio][0]);
		aleatorio = new Random().nextInt(tamanio);
		this.setLlegada(plano[aleatorio][tamanio - 1]);
	
	}
	
	private void crearMapa(int tamanio){
		plano = new Esquina[tamanio][tamanio];
		
		// Cargo las esquinas en la matriz
		for (int i = 0; i < tamanio; i++) {
			for (int j = 0; j < tamanio; j++) {
				PosicionMapa unaPos = new PosicionMapa(i, j);
				plano[i][j] = new Esquina();
				plano[i][j].setCoordenada(unaPos);
			}
		}

		// seteo las calles que unen las esquinas

		// seteo calles horizontales
		for (int i = 0; i < tamanio; i++) {
			for (int j = 1; j < tamanio; j++) {
				Calle unaCalle = new Calle();
				callesDelMapa.add(unaCalle);
				plano[i][j].setCalleOeste(unaCalle);
				plano[i][j - 1].setCalleEste(unaCalle);
				unaCalle.setearEntreEsquinas(plano[i][j], plano[i][j - 1]);
			}
		}

		// seteo calles verticales
		for (int j = 0; j < tamanio; j++) {
			for (int i = 1; i < tamanio; i++) {
				Calle unaCalle = new Calle();
				callesDelMapa.add(unaCalle);
				plano[i - 1][j].setCalleSur(unaCalle);
				plano[i][j].setCalleNorte(unaCalle);
				unaCalle.setearEntreEsquinas(plano[i - 1][j], plano[i][j]);
			}
		}

	}

	public void setLargada(Esquina unaEsquina) {
		this.largada = unaEsquina;
		unaEsquina.setComoLargada();
		
	}

	public void setLlegada(Esquina unaEsquina) {
		this.llegada = unaEsquina;
		unaEsquina.setComoMeta();
	}
	

	public Esquina getLlegada() {
		return this.llegada;
	}

	public Esquina getLargada() {
		return this.largada;
	}

	public void cargarObstaculos(int cantObstaculos) {
		ArrayList<Calle> callesACargar = (ArrayList<Calle>) callesDelMapa.clone();
		ArrayList<Obstaculo> listaDeObstaculos = new ArrayList<Obstaculo>();
		listaDeObstaculos.add(new Piquete());
		GeneradorDeNumerosAleatorios generadorAleatorio = new GeneradorVerdadero();
		listaDeObstaculos.add(new ControlPolicial(generadorAleatorio));
		listaDeObstaculos.add(new Pozo());
		Random aleatorio = new Random();
		for (int i = 0; i < cantObstaculos; i++) {
			Calle calleActual = callesACargar.remove(aleatorio.nextInt(callesACargar.size()));
			calleActual.setObstaculo(listaDeObstaculos.get(aleatorio.nextInt(listaDeObstaculos.size())));
		}
	}

	public void cargarSorpresas(int cantSorpresas) {
		ArrayList<Calle> callesACargar = (ArrayList<Calle>) callesDelMapa.clone();
		ArrayList<Sorpresa> listaDeSorpresas = new ArrayList<Sorpresa>();
		listaDeSorpresas.add(new SorpresaCambioDeVehiculo());
		listaDeSorpresas.add(new SorpresaDesfavorable());
		listaDeSorpresas.add(new SorpresaFavorable());
		Random aleatorio = new Random();
		for (int i = 0; i < cantSorpresas; i++) {
			Calle calleActual = callesACargar.remove(aleatorio.nextInt(callesACargar.size()));
			calleActual.setSorpresa(listaDeSorpresas.get(aleatorio.nextInt(listaDeSorpresas.size())));
		}
	}

	public Esquina getEsquinaEnPosicion(int x, int y) {
		return plano[x][y];
	}

	public int getTamanio() {
		return this.tam;
	}

	public Element serializar(){
		Element nodoMapa = new Element("Mapa");
		
		
		nodoMapa.setAttribute("tamanio", Integer.toString(this.tam));
		
		Element nodoLargada = new Element("Largada");
		nodoLargada.addContent(this.largada.serializar());
		nodoMapa.addContent(nodoLargada);
		
		Element nodoLlegada = new Element("Llegada");
		nodoLlegada.addContent(this.llegada.serializar());
		nodoMapa.addContent(nodoLlegada);
		
		return nodoMapa;	
		}
	
	public Mapa(Element nodoMapa,Conductor unConductor){
		this.tam = Integer.parseInt(nodoMapa.getAttributeValue("tamanio"));
		
		this.crearMapa(this.tam);

		Element nodoLargada = nodoMapa.getChild("Largada");
		Esquina largada = new Esquina(nodoLargada.getChild("Esquina"));
		this.setLargada(plano[unConductor.getUbicacion().getCoordenadaX()][unConductor.getUbicacion().getCoordenadaY()]);
		
		
		Element nodoLlegada = nodoMapa.getChild("Llegada");
		Esquina llegada = new Esquina(nodoLlegada.getChild("Esquina"));
		this.setLlegada(plano[llegada.getCoordenadaX()][llegada.getCoordenadaY()]);
		
		

		
		
				
		
	}
}
